home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 June: Reference Library / Dev.CD Jun 95 / Dev.CD Jun 95.toast / What's New? / New System Software Extensions / QuickDraw 3D ß / Programming / SampleCode / Modeller ƒ / Modeller_AEVT.c < prev    next >
Encoding:
Text File  |  1995-03-31  |  22.0 KB  |  830 lines  |  [TEXT/MPS ]

  1. //    Modeller_AEVT.c
  2. //
  3. //    Apple Event Routines for the modeller App.  Contains AppleEvent Handlers and senders for
  4. //  the modeller app.
  5. //        
  6. //    Author:        Nick Thompson, 11/24/94
  7. //
  8. //    Modification History:
  9. //
  10. //    11/26/94        nick        clean up, remove old TE references from dragtext, remove
  11. //                                all other dead code
  12. //    11/24/94        nick        Initial Cut - factored code from Modeller event, added
  13. //                                 Drag related events for debugging (you can't debug the 
  14. //                                handler, but if the handler sends an event you can debug
  15. //                                the AE handler).
  16. //
  17. //    Copyright © 1992-94 Apple Computer, Inc., All Rights Reserved
  18. //
  19. //    To Do:
  20. //        a number of items are "duplicated" in the event we send to ourselves
  21. //        we send the window and the document (the doc reference is stored in the
  22. //        window refcon, window is stored in the doc)
  23. //
  24.  
  25. #include <AppleEvents.h>
  26. #include <Drag.h>
  27. #include <GestaltEqu.h>
  28. #include <Memory.h>
  29. #include <SegLoad.h>
  30.  
  31. #include "Modeller_prototypes.h"
  32. #include "Modeller_resources.h"
  33. #include "Modeller_offscreen.h"
  34. #include "Modeller_DDTEUtilities.h"
  35. #include "Modeller_globals.h"
  36.  
  37. #include "Modeller_AEVT.h"
  38. #include "Modeller_Traps.h"
  39. #include "Modeller_Document.h"
  40. #include "Modeller_file.h"
  41. #include "Modeller_PICTImport.h"
  42. #include "Modeller_camera.h"
  43. #include "Modeller_file.h"
  44.  
  45. #ifdef PODIUM_APP
  46. #include "Modeller_Podium.h"
  47. #endif
  48.  
  49. #include "QD3D.h"
  50. #include "QD3DDrawContext.h"
  51. #include "QD3DGroup.h"
  52. #include "QD3DIO.h"
  53. #include "QD3DPick.h"
  54. #include "QD3DShader.h"
  55. #include "QD3DStorage.h"
  56. #include "QD3DTransform.h"
  57. #include "QD3DView.h"
  58.  
  59.  
  60. #define    kGestaltTrap    0xA0AD
  61.  
  62. #include "Modeller_AEVT.h"
  63.  
  64.  
  65. // local variables - to this file
  66.  
  67. static AEAddressDesc        pSelfAddress;            // A self-addressed address descriptor record
  68. static ProcessSerialNumber    pSelfPSN;                // This application's psn
  69. static AEDesc                pnilDesc;                // A nil descriptor record
  70.  
  71. // this defines a suite of events for dispatching drags
  72. static const AEEventClass    kDraggingClass             = 'drag' ;
  73.     static const AEEventID        kDragDrawID                = 'draw' ;
  74.     static const AEEventID        kDragSendID                = 'send' ;
  75.     static const AEEventID        kDragReceiveID            = 'recv' ;
  76.     static const AEEventID        kDragTrackID            = 'trak' ;
  77.     static const AEEventID        kDragDragID                = 'drag' ;
  78.     
  79. //
  80.  
  81. static const AEKeyword    keyPrivateData                = 'priv' ;
  82.  
  83.  
  84. // AppleEvent Error Handling....
  85. //----------------------------------------------------------------------------------
  86. //  If an error has occurred, I check the user interaction level. If I can            
  87. //    interact with the user, I put up a dialog and exit the application; otherwise,
  88. //    I just exit the application.
  89. //
  90. //    ***NOTE: Real applications would not handle errors in this fashion!  If they
  91. //    cannot interact with the user, they should abort the Apple event handler and
  92. // return the error in the reply parameter.
  93.  
  94. void FailIfErr (OSErr  error)
  95. {
  96.     OSErr        interactErr = noErr ;
  97.     if (error != noErr)
  98.     {
  99.         if ((interactErr = AEInteractWithUser(kNoTimeOut, nil, nil)) == noErr) {    
  100.                                     // Can we interact?
  101.             AlertUser(error);        // Yes, so put up the dialog.
  102.             ExitToShell();
  103.         }
  104.     }
  105. }
  106.  
  107. //----------------------------------------------------------------------------------
  108. // Display an alert for the user to indicate that an error has occurred.
  109. // This approach would not really be good for a real app - hard coding 
  110. // strings in this manner would be really hard to localise.     But this approach
  111. // is good for programming because it gives us the error code.    
  112.  
  113. void AlertUser (short  error)
  114. {
  115.     short        itemHit;
  116.     Str255        defaultMessage = "\pAn error was encountered" ;
  117.     Str255        message ;
  118.     Str255        errNo ;
  119.  
  120.     if( error < 0 ) {
  121.         BlockMove( &defaultMessage[1], &message[1], defaultMessage[0] );
  122.         message[0] = defaultMessage[0] ;
  123.     }
  124.     else {
  125.         GetIndString(message, rErrorStringIndex, error);
  126.     }
  127.     
  128.     NumToString( error, errNo ) ;
  129.     
  130.     ParamText(    message,
  131.                 (ConstStr255Param)"\p (",
  132.                 errNo,
  133.                 (ConstStr255Param)"\p).");    // [pwpc]
  134.  
  135.     itemHit = Alert(rUserAlert, nil);
  136. }
  137.  
  138. //----------------------------------------------------------------------------------
  139.  
  140. void    FatalError(short error)
  141. {
  142.  
  143.     Str255        message ;
  144.  
  145.     GetIndString(message, rFatalErrorStringIndex, error);
  146.     ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");    // [pwpc]
  147.     (void)StopAlert( rFatalAlert, nil ) ;
  148.     ExitToShell() ;
  149. }
  150.  
  151. //-----------------------------------------------------------------------
  152. // call this to init the AE stuff in this file
  153.  
  154. void InitAEStuff( void ) 
  155. {
  156.     // Set up the self-addressed descriptor record.
  157.     pSelfPSN.highLongOfPSN = 0;
  158.     pSelfPSN.lowLongOfPSN = kCurrentProcess;        // Use this instead of GetCurrentProcess
  159.     FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&pSelfPSN,sizeof(ProcessSerialNumber),&pSelfAddress));
  160.     pnilDesc.descriptorType = typeNull;            // Initialize the global nil descriptor record.
  161.     pnilDesc.dataHandle = nil;
  162.     
  163.     RegisterMyEvents() ;                            // and finally register appleEvent handlers
  164.     
  165. }
  166.  
  167. //-----------------------------------------------------------------------
  168. // returns true if the platform supports appleevents - we won't run
  169. // if it doesn't
  170.  
  171. Boolean SupportsAEVT(void)
  172. {
  173.     OSErr err;
  174.     long response;
  175.     
  176.     if (!myTrapAvailable(kGestaltTrap))
  177.         return false;
  178.     
  179.     err = Gestalt(gestaltAppleEventsAttr,&response);
  180.     if (err!=noErr)
  181.         return false;
  182.         
  183.     return (response && (response << gestaltAppleEventsPresent));
  184. }
  185.  
  186. //-----------------------------------------------------------------------
  187. // called to process high level appleevents
  188.  
  189. void DoHighLevelEvent(EventRecord *ev)
  190. {
  191.     OSErr err;
  192.     
  193.     err = AEProcessAppleEvent(ev);    
  194. }
  195.  
  196. //-----------------------------------------------------------------------
  197. // called to register our appleevent handlers
  198.  
  199. void RegisterMyEvents(void)
  200. {
  201.     OSErr err;
  202.     
  203.     if (!SupportsAEVT())
  204.         return;
  205.     
  206.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(MyAEHandleOAPP),0L,false);
  207.     if (err!=noErr)
  208.         return;
  209.                 
  210.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(MyAEHandleODOC),0L,false);
  211.     if (err!=noErr)
  212.         return;
  213.                 
  214.     err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(MyAEHandlePDOC),0L,false);
  215.     if (err!=noErr)
  216.         return;
  217.                 
  218.     err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc(MyAEHandleQUIT),0L,false);
  219.     if (err!=noErr)
  220.         return;            
  221.  
  222.  
  223.     // drag stuff handlers
  224.     err = AEInstallEventHandler(kDraggingClass,kDragReceiveID,NewAEEventHandlerProc(MyAEHandleDragRecv),0L,false);
  225.     if (err!=noErr)
  226.         return;            
  227.  
  228. }
  229.  
  230. //-----------------------------------------------------------------------
  231. // open application event handler for the core event suite, 
  232. // by default we just want a blank new document
  233.  
  234. pascal OSErr MyAEHandleOAPP(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  235. {
  236.     OSErr err = noErr ;
  237.  
  238. #ifndef PODIUM_APP
  239.     DoNewDocument();
  240. #endif
  241.     return err;
  242. }
  243.  
  244.  
  245. //-----------------------------------------------------------------------
  246. // handler for the open document appleevent handler
  247.  
  248. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  249. {
  250.     FSSpec         myFSS;
  251.     AEDescList    docList;
  252.     OSErr        err,
  253.                 ignoreErr;
  254.     long        index,
  255.                 itemsInList;
  256.     Size         actualSize;
  257.     AEKeyword    keywd;
  258.     DescType    returnedType;
  259.  
  260.     
  261.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  262.     if (err == noErr) {
  263.     
  264.         // see how many descriptor items are in the list
  265.         // this is the number of documents we want to open
  266.         err = AECountItems(&docList,&itemsInList);
  267.  
  268.         // now get each descriptor record from the list
  269.         // coerce the returned data to an FSSpec record, and
  270.         // open the asoociated file
  271.         
  272.         for (index=1; index <= itemsInList && err == noErr; index++) {
  273.         
  274.             err = AEGetNthPtr(    &docList, 
  275.                                 index,
  276.                                 typeFSS,
  277.                                 &keywd,
  278.                                 &returnedType,
  279.                                 (Ptr)&myFSS,
  280.                                 sizeof(myFSS),
  281.                                 &actualSize);
  282.     
  283.             if (err == noErr)    {
  284.             
  285.                 FInfo        fndrInfo ;
  286.                 
  287.                 // we now have a valid FSSpec to reference the file, we need to know 
  288.                 // what type the file is to determine which file open function to call
  289.                 // we can determine this from the finder info for the file
  290.                 
  291.                 err = FSpGetFInfo( &myFSS, &fndrInfo );    
  292.                 
  293.                 // if we got that ok, then we switch on the file  
  294.                 // type (we don't care about the creator type)    
  295.                         
  296.                 if (err == noErr)    {
  297.                 
  298.                     switch( fndrInfo.fdType ) {
  299.                         case 'PICT':
  300.                             break ;
  301.                             
  302.                         case 'TEXT':
  303.                         case '3DMF':
  304.                             err = DoOpenFile(&myFSS);
  305.                             break ;
  306.                         
  307.                         default:
  308.                             break ;
  309.                     }
  310.                 }
  311.             }
  312.         }
  313.         ignoreErr = AEDisposeDesc(&docList);
  314.     }
  315.     return err ;
  316. }
  317.  
  318. //-----------------------------------------------------------------------
  319. // handler for the print document event handler
  320.  
  321. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  322. {
  323.     FSSpec         myFSS;
  324.     AEDescList    docList;
  325.     OSErr        err;
  326.     long        index,
  327.                 itemsInList;
  328.     Size         actualSize;
  329.     AEKeyword    keywd;
  330.     DescType    returnedType;
  331.  
  332.     
  333.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  334.     if (err == noErr) {
  335.     
  336.         // see how many descriptor items are in the list
  337.         // this is the number of documents we want to open
  338.         err = AECountItems(&docList,&itemsInList);
  339.  
  340.         // now get each descriptor record from the list
  341.         // coerce the returned data to an FSSpec record, and
  342.         // open the asoociated file
  343.         
  344.         for (index=1; index <= itemsInList && err == noErr; index++) {
  345.         
  346.             err = AEGetNthPtr(    &docList, 
  347.                                 index,
  348.                                 typeFSS,
  349.                                 &keywd,
  350.                                 &returnedType,
  351.                                 (Ptr)&myFSS,
  352.                                 sizeof(myFSS),
  353.                                 &actualSize);
  354.     
  355.             if (err == noErr)    {                    
  356.                 // err = HandlePrintDoc( &myFSS );
  357.                 err = errAEEventNotHandled ;         // we don't do this yet...
  358.             }
  359.         }
  360.         err = AEDisposeDesc(&docList);
  361.     }
  362.     return err ;
  363. }
  364.  
  365. //-----------------------------------------------------------------------
  366. // quit appleevent handler
  367.  
  368. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  369. {
  370.     OSErr             err = noErr ;        // used as return value
  371.  
  372.     
  373.     // close all windows and signal to Quit
  374.  
  375.     gQuitting = true;
  376.         
  377.     // attempt to close all documents
  378.     if( CloseAllDocuments() == false )
  379.         return userCanceledErr ;    // couldn't close them, so indicate the user cancelled
  380.         
  381.  
  382.     // if we closed everything up successfully, we can return noErr, otherwise
  383.     // indicate to sender of the 'quit' aevt that we canceled
  384.     
  385.     if (gQuitting) {
  386.         gQuit = true;                        // user didn't cancel
  387.         err = AEDisposeDesc(&pSelfAddress);    // Dispose of my self-addressed descriptor.
  388.     }
  389.     else {
  390.         err = userCanceledErr ;
  391.     }
  392.             
  393.     return err ;
  394. }
  395.  
  396. //-----------------------------------------------------------------------
  397. // drag receive appleevent handler
  398.  
  399. pascal OSErr MyAEHandleDragRecv(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  400. {
  401.  
  402.     AEDesc                myDesc;
  403.     OSErr                err;
  404.     OSErr                ignoreErr ;
  405.     TQ3Object             objects = nil;
  406.  
  407.  
  408.     err = AEGetParamDesc(theAppleEvent,keyPrivateData,typeChar,&myDesc);
  409.     if (err == noErr) {
  410.     
  411.         // try to load all of the items we stuffed into the apple event
  412.         myPrivateDataHdl        thePrivateData = (myPrivateDataHdl)myDesc.dataHandle ;
  413.         OSType                    theDragType = (**thePrivateData).myTypeOfData ;
  414.         DocumentPtr             theDocument = (**thePrivateData).myDocument ;
  415.         long                    dataSize = (**thePrivateData).myDataSize ;
  416.         WindowPtr                theWindow = (**thePrivateData).myWindow  ;
  417.         Point                    theLocation = (**thePrivateData).myLocation ;
  418.         Handle                    dataHdl = NewHandle( dataSize ) ;
  419.         
  420.         // sanity check
  421.         if( dataSize > GetHandleSize( myDesc.dataHandle )) {
  422.             ignoreErr = AEDisposeDesc(&myDesc);
  423.             return paramErr ;
  424.         }
  425.         
  426.         // check we could create the data handle OK
  427.         if( dataHdl == nil ) {
  428.             ignoreErr = AEDisposeDesc(&myDesc);
  429.             return MemError() ;
  430.         }
  431.  
  432.         // copy the data from the descriptor to our handle
  433.         BlockMove( &(**thePrivateData).myData, *dataHdl, dataSize );
  434.         
  435.         // we need to get rid of the descriptor, to save on memory
  436.         err = AEDisposeDesc(&myDesc);
  437.         
  438.         // process the information from the drag
  439.         if( theDragType == '3DMF' ) {
  440.         
  441.             TQ3SharedObject    viewHints ;
  442.         
  443.             // do this on receipt of a drag of type 3DMF    
  444.  
  445.             TQ3FileObject         fd;
  446.             TQ3StorageObject         storage;
  447.  
  448.             // Lock and load
  449.             MoveHHi( dataHdl ) ;
  450.             HLock(  dataHdl ) ;
  451.             
  452.             storage = Q3MemoryStorage_New((const unsigned char *) *dataHdl,
  453.                 (unsigned long) dataSize );
  454.                 
  455.             HUnlock( dataHdl ) ;
  456.             
  457.             if (storage == nil)
  458.                 goto bail;
  459.             
  460.             fd = Q3File_New();
  461.             Q3File_SetStorage(fd, storage);
  462.             Q3Object_Dispose(storage);
  463.             
  464.             if (fd == nil)
  465.                 goto bail;
  466.  
  467.             Modeller_ReadScene(
  468.                 fd,
  469.                 false,
  470.                 &viewHints,
  471.                 &theDocument->documentGroup) ;
  472.  
  473. #ifdef PODIUM_APP
  474.             {
  475.             // we really want the obect to be centered about the 
  476.             // drop location.
  477.             GrafPtr        savedPort ;
  478.             
  479.             extern void Podium_UpdateDrawContextFromDropRect( DocumentPtr theDocument ) ;
  480.  
  481.             GetPort( &savedPort ) ;
  482.             SetPort( theWindow ) ;
  483.             GlobalToLocal(&theLocation) ;
  484.             
  485.             // make the droprect be located top left at (0, 0)
  486.             OffsetRect( &theDocument->dropArea, -theDocument->dropArea.left,  -theDocument->dropArea.top );
  487.             OffsetRect( &theDocument->dropArea, 
  488.                             (theLocation.h - ((theDocument->dropArea.right - theDocument->dropArea.left)/2)), 
  489.                             (theLocation.v - ((theDocument->dropArea.bottom - theDocument->dropArea.top)/2)) );
  490.             Podium_UpdateDrawContextFromDropRect( theDocument ) ;
  491.             SetPort(savedPort) ;
  492.             }
  493. #endif
  494.             
  495.             ModellerDocument_UpdateView( theDocument, viewHints ) ;
  496.             
  497.             AdjustLightsPositions(theDocument) ;
  498.         
  499.             if (viewHints)
  500.                 Q3Object_Dispose(viewHints);
  501.         
  502.             Q3Object_Dispose(fd);
  503.         }        
  504.         else if( theDragType == 'PICT' ){
  505.  
  506.             // do this on receipt of a drag of type PICT
  507.  
  508.             TQ3StoragePixmap textureImage;
  509.             PicHandle        thePicture = (PicHandle)dataHdl ;
  510.  
  511.             //Create a texture pixmap
  512.             MoveHHi((Handle) thePicture );
  513.             HLock((Handle) thePicture );
  514.  
  515.             if( TextureFromPICT((PicHandle) thePicture, &textureImage) == kQ3False ) {
  516.                 Alert(130, 0L);
  517.                 goto bail;
  518.             }
  519.             
  520.             if( AddTextureToDocument( theDocument, &textureImage) != kQ3Success ) {
  521.                 Alert(130, 0L);
  522.                 goto bail;
  523.             }
  524.             HUnlock((Handle)thePicture);
  525.             
  526.         }        
  527.         else if( theDragType == flavorTypeHFS ){
  528.         
  529.             // do this on receipt of an HFS flavor (a file from the finder)
  530.             HFSFlavor        theHFSFlavor ;
  531.  
  532.             // lock down the handle
  533.             MoveHHi( dataHdl ) ;
  534.             HLock( dataHdl ) ;
  535.             
  536.             theHFSFlavor = *((HFSFlavor *)*dataHdl) ;
  537.  
  538.             
  539.             if( theHFSFlavor.fileType == 'TEXT' || theHFSFlavor.fileType == '3DMF') {
  540.             
  541.                 OSErr                result;
  542.                 short                refNum;
  543.                 DocumentPtr         theDocument;
  544.                 FInfo                fndrInfo ;
  545.                 TQ3Boolean            isText ;
  546.             
  547.                 // we assume the FSSpec passed in was valid, get the file information
  548.                 // we need to know the file type, this routine may get called by an appleEvent
  549.                 // handler, so we can't assume a type, we need to get it from the fsspec.
  550.                 
  551.                 FSpGetFInfo( &theHFSFlavor.fileSpec, &fndrInfo ) ;
  552.                 
  553.                 // pull out the file type
  554.                 
  555.                 isText = ( fndrInfo.fdType == 'TEXT') ;
  556.                 
  557.                 if ((result = FSpOpenDF(&theHFSFlavor.fileSpec, fsRdWrPerm, &refNum)) != noErr)
  558.                     return(result);
  559.         
  560.                 theDocument->fRefNum = refNum;
  561.                 theDocument->theFileSpec = theHFSFlavor.fileSpec ;
  562.                 SetCursor(*GetCursor(watchCursor));
  563.                 ReadDocumentFile( theDocument, isText ) ;
  564.                 SetCursor(&qd.arrow);
  565.             
  566.             } else if( theHFSFlavor.fileType == 'PICT' && theDocument && theDocument->documentGroup) {
  567.  
  568.                 PicHandle        thePict;
  569.                 TQ3StoragePixmap textureImage;
  570.                 
  571.                 // get the picture from the file
  572.                 thePict = OpenPICTFile(&theHFSFlavor.fileSpec);
  573.                 
  574.                 // make a texture
  575.                 TextureFromPICT( thePict, &textureImage);
  576.                 AddTextureToDocument( theDocument, &textureImage);
  577.                 
  578.                 // and free the space occupied by the picture
  579.                 KillPicture(thePict) ;
  580.             
  581.             }
  582.             else
  583.                 dataSize = 0;    // need better handling here...
  584.         
  585.         
  586.         }
  587.  
  588.         // we can free up the memory now...
  589.         DisposeHandle( dataHdl ) ;
  590.         dataHdl = nil ;
  591.         
  592.         //    If we actually received something, insert it into the destination.
  593.     
  594.         if (dataSize != 0) {
  595.     
  596.             theDocument->dirty = true;
  597.                 AdjustLightsPositions( theDocument);
  598.                 
  599.                 AdjustCamera(theDocument,
  600.                     theWindow->portRect.right - theWindow->portRect.left,
  601.                     theWindow->portRect.bottom - theWindow->portRect.top);
  602.  
  603.             //    Draw everything into offscreen pixmap.
  604.             if (DrawOffscreen(theDocument)) {
  605.                 SetPort( theWindow ) ;
  606.                 InvalRect( &theWindow->portRect ) ;
  607.                 DrawOnscreen(theDocument);
  608.             } 
  609.         }    
  610.     }
  611.     return err ;
  612.     
  613. bail:
  614.     return(memFullErr);
  615. }
  616.  
  617. //-----------------------------------------------------------------------
  618. // A P P L E E V E N T   S E N D E R   R O U T I N E S . . .
  619. //-----------------------------------------------------------------------
  620. // These routines are used to send ourselves AppleEvents, this is useful 
  621. // for a number of reasons, ultimately it would help make us scriptable if
  622. // we implemented some of the OSL, also it's a big help for debugging drags.
  623. //
  624. // Its not really easy to do source level debugging of drag handlers and 
  625. // trackers.  By packaging up the information into an appleevent and sending
  626. // it to ourselves, we can to source level debugging of the drag in the AE 
  627. // handler.
  628.  
  629.  
  630. //----------------------------------------------------------------------------------//
  631. //    Send a Quit Application Apple Event to myself to terminate this app.        
  632.  
  633. void SendQuitApp( void )
  634. {
  635.     AppleEvent    myAppleEvent, reply;
  636.     
  637.     //    Create the Apple Event.
  638.     FailIfErr(AECreateAppleEvent( kCoreEventClass, 
  639.                                   kAEQuitApplication, 
  640.                                   &pSelfAddress,
  641.                                   kAutoGenerateReturnID, 
  642.                                   kAnyTransactionID, 
  643.                                   &myAppleEvent));
  644.                                   
  645.     //    Send the Apple Event.
  646.       FailIfErr(AESend( &myAppleEvent, 
  647.                         &reply, 
  648.                         kAENoReply+kAENeverInteract, 
  649.                         kAENormalPriority,
  650.                         kAEDefaultTimeout, 
  651.                         nil, 
  652.                         nil));
  653.                         
  654.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  655. } // SendQuitApp
  656.  
  657. //----------------------------------------------------------------------------------//
  658. //    Send a Open Document Application Apple Event to myself to open a document.        
  659.  
  660. void SendOpenDoc(FSSpec *myFSSpec)
  661. {
  662.      AppleEvent    myAppleEvent;
  663.     AppleEvent    defReply;
  664.     AEDescList    docList;
  665.  
  666.     OSErr         ignoreErr;
  667.     
  668.     myAppleEvent.dataHandle = nil;
  669.     docList.dataHandle  = nil;
  670.     defReply.dataHandle = nil;
  671.         
  672.     // Create empty list and add one file spec
  673.     FailIfErr(AECreateList(nil,0,false, &docList));
  674.     
  675.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  676.         
  677.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  678.                                     kAEOpenDocuments,
  679.                                     &pSelfAddress,
  680.                                     kAutoGenerateReturnID,
  681.                                     kAnyTransactionID,
  682.                                     &myAppleEvent));
  683.  
  684.     // Put Params into our event and send it
  685.  
  686.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  687.                               keyDirectObject,
  688.                               &docList));
  689.  
  690.     FailIfErr(AESend( &myAppleEvent,
  691.                       &defReply,
  692.                       kAENoReply+kAENeverInteract,
  693.                       kAENormalPriority,
  694.                       kAEDefaultTimeout,
  695.                       nil,
  696.                       nil));
  697.         
  698.         
  699.     if (myAppleEvent.dataHandle) 
  700.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  701.         
  702.     if (docList.dataHandle) 
  703.         ignoreErr = AEDisposeDesc(&docList);
  704.             
  705. }    // SendOpenDoc 
  706.  
  707. //----------------------------------------------------------------------------------//
  708. //    Send a Print Document Application Apple Event to myself to open a document.        
  709.  
  710.  
  711.  
  712.  
  713. void SendPrintDoc(FSSpec *myFSSpec)
  714. {
  715.      AppleEvent    myAppleEvent;
  716.     AppleEvent    defReply;
  717.     AEDescList    docList;
  718.  
  719.     OSErr         ignoreErr;
  720.     
  721.     myAppleEvent.dataHandle = nil;
  722.     docList.dataHandle  = nil;
  723.     defReply.dataHandle = nil;
  724.         
  725.     // Create empty list and add one file spec
  726.     FailIfErr(AECreateList(nil,0,false, &docList));
  727.     
  728.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  729.         
  730.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  731.                                     kAEPrintDocuments,
  732.                                     &pSelfAddress,
  733.                                     kAutoGenerateReturnID,
  734.                                     kAnyTransactionID,
  735.                                     &myAppleEvent));
  736.  
  737.     // Put Params into our event and send it
  738.  
  739.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  740.                               keyDirectObject,
  741.                               &docList));
  742.  
  743.     FailIfErr(AESend( &myAppleEvent,
  744.                       &defReply,
  745.                       kAENoReply+kAENeverInteract,
  746.                       kAENormalPriority,
  747.                       kAEDefaultTimeout,
  748.                       nil,
  749.                       nil));
  750.         
  751.         
  752.     if (myAppleEvent.dataHandle) 
  753.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  754.         
  755.     if (docList.dataHandle) 
  756.         ignoreErr = AEDisposeDesc(&docList);
  757.             
  758. }    // SendOpenDoc 
  759.  
  760.  
  761.  
  762. //----------------------------------------------------------------------------------
  763. //    Send a drag receive Apple Event to myself to handle the receipt of a drag.        
  764.  
  765.  
  766. void SendDragRecv( myPrivateDataHdl privateHdl )
  767. {
  768.      AppleEvent    myAppleEvent;
  769.     AppleEvent    defReply;
  770.  
  771.     OSErr         ignoreErr;
  772.     
  773.     ProcessSerialNumber        myPSN ;
  774.     
  775.     AEDesc            myAddress ;
  776.     char            cMemTags = HGetState((Handle)privateHdl);    // save the state of the handle in case
  777.                                                                 // it was already locked before we were
  778.                                                                 // called
  779.     
  780.     myAppleEvent.dataHandle = nil;
  781.     defReply.dataHandle = nil;
  782.  
  783.     // the static pSelfAddress that we create an usually use will cause the 
  784.     // AE handler to be caused directly (less overhead).  We DON'T WANT THAT
  785.     // to happen here.  The reason being that the handler for this event needs
  786.     // to be called in our main event loop, not directly at the send.  Doing things
  787.     // this way lets us get out of the Drag Managers context, back into our own.
  788.     // that in turn lets us use a high level debugger.
  789.     
  790.     
  791.     FailIfErr(GetCurrentProcess(&myPSN)) ;
  792.     FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&myPSN,sizeof(ProcessSerialNumber),&myAddress));
  793.  
  794.     FailIfErr(AECreateAppleEvent(    kDraggingClass,
  795.                                     kDragReceiveID,
  796.                                     &myAddress,
  797.                                     kAutoGenerateReturnID,
  798.                                     kAnyTransactionID,
  799.                                     &myAppleEvent));
  800.  
  801.     // lock down the handle
  802.     MoveHHi( (Handle)privateHdl );
  803.     HLock( (Handle)privateHdl );
  804.     
  805.     // Put Params into our event and send it
  806.  
  807.     FailIfErr(AEPutParamPtr( &myAppleEvent,
  808.                              keyPrivateData,
  809.                              typeChar,
  810.                              *privateHdl,
  811.                              GetHandleSize( (Handle)privateHdl )));
  812.  
  813.     // restore the state of the handle (effectively the same as HUnlock)
  814.     HSetState((Handle)privateHdl, cMemTags) ;
  815.  
  816.     FailIfErr(AESend( &myAppleEvent,
  817.                       &defReply,
  818.                       kAENoReply+kAENeverInteract,
  819.                       kAENormalPriority,
  820.                       kAEDefaultTimeout,
  821.                       nil,
  822.                       nil));
  823.         
  824.         
  825.     if (myAddress.dataHandle) 
  826.         ignoreErr = AEDisposeDesc(&myAddress);
  827.  
  828.     if (myAppleEvent.dataHandle) 
  829.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  830. }